/*******************************************************************************
 * Copyright (c) 2012-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.api.core.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;

import javax.ws.rs.core.MediaType;

/**
 * Helps getting content type of file.
 *
 * @author andrew00x
 */
public class ContentTypeGuesser {
    private static final Logger LOG = LoggerFactory.getLogger(ContentTypeGuesser.class);

    private static String defaultContentType = MediaType.APPLICATION_OCTET_STREAM;

    public synchronized static void setDefaultContentType(String myDefaultContentType) {
        defaultContentType = myDefaultContentType;
    }

    public synchronized static String getDefaultContentType() {
        return defaultContentType;
    }

    private static Properties properties = new Properties();

    static {
        final String filePath = System.getProperty("org.eclipse.che.content-types");
        URL resource = null;
        if (filePath != null) {
            resource = Thread.currentThread().getContextClassLoader().getResource(filePath);
        }
        if (resource == null) {
            resource = Thread.currentThread().getContextClassLoader().getResource("content-types.properties");
        }
        if (resource != null) {
            try (InputStream stream = resource.openStream()) {
                properties.load(stream);
                LOG.info("Successfully load content types from {}", resource);
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }
    }

    public static String guessContentType(java.io.File file) {
        String contentType = null;
        final String name = file.getName();
        final int dot = name.lastIndexOf('.');
        if (dot > 0) {
            final String ext = name.substring(dot + 1);
            if (!ext.isEmpty()) {
                // by file extensions
                contentType = properties.getProperty(ext);
            }
        }
        if (contentType == null) {
            // by full file name.
            contentType = properties.getProperty(name);
        }
        /* Commented due to on Amazon infra with power instances. JVM crashes with multi-thread access (no problem with single thread).

        *** glibc detected *** /usr/local/jdk/bin/java: double free or corruption (out): 0x00007f22f0007820 ***
        ======= Backtrace: =========
        /lib64/libc.so.6[0x3da68760e6]
        /lib64/libc.so.6[0x3da6878c13]
        /lib64/libglib-2.0.so.0(g_array_free+0x7a)[0x3da7c13dda]
        /lib64/libgio-2.0.so.0[0x3da9c352f4]
        /lib64/libgobject-2.0.so.0(g_object_unref+0x15f)[0x3da8c0dacf]
        /usr/local/jdk1.7.0_17/jre/lib/amd64/libnio.so(Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio+0xa2)[0x7f24aa7c7232]
        [0x7f24d3186db1]

        if (contentType == null) {
            try {
                // if content type is null use JDK.
                contentType = java.nio.file.Files.probeContentType(file.toPath());
            } catch (IOException e) {
                LOG.warn(e.getMessage(), e);
            }
        }*/
        return contentType == null ? getDefaultContentType() : contentType;
    }

    public static String guessContentType(String name) {
        String contentType = null;
        final int dot = name.lastIndexOf('.');
        if (dot > 0) {
            final String ext = name.substring(dot + 1);
            if (!ext.isEmpty()) {
                // by file extensions
                contentType = properties.getProperty(ext);
            }
        }
        if (contentType == null) {
            // by full file name.
            contentType = properties.getProperty(name);
        }
        return contentType == null ? getDefaultContentType() : contentType;
    }

    private ContentTypeGuesser() {
    }
}
